package com.baiyimi.pan.ui.module;

import com.baiyimi.pan.printer.Printer;
import com.baiyimi.pan.server.util.ConfigureReader;
import com.baiyimi.pan.ui.callback.*;

import javax.imageio.*;
import java.io.*;
import java.sql.SQLException;
import java.awt.event.*;
import javax.swing.border.*;
import java.awt.*;
import javax.swing.event.*;

import javax.swing.*;
import java.text.*;
import java.util.*;


public class ServerUIModule extends PanDynamicWindow {

    protected static JFrame window;
    private static SystemTray tray;
    private static TrayIcon trayIcon;
    private static JTextArea output;
    private static ServerUIModule instance;
    private static SettingWindow sw;
    private static FSViewer fsv;
    private static OnCloseServer cs;
    private static OnStartServer ss;
    private static GetServerStatus st;
    private static GetServerTime ti;
    private static JButton start;
    private static JButton stop;
    private static JButton resatrt;
    private static JButton setting;
    private static JButton fileIOUtil;
    private static JButton exit;
    private static JLabel serverStatusLab;
    private static JLabel portStatusLab;
    private static JLabel logLevelLab;
    private static JLabel bufferSizeLab;
    private static final String S_STOP = "停止[Stopped]";
    private static final String S_START = "运行[Running]";
    private static final String S_STARTING = "启动中[Starting]...";
    private static final String S_STOPPING = "停止中[Stopping]...";
    protected static final String L_ALL = "记录全部(ALL)";
    protected static final String L_EXCEPTION = "仅异常(EXCEPTION)";
    protected static final String L_NONE = "不记录(NONE)";
    private SimpleDateFormat sdf;
    /**
     * 窗口原始宽度
     */
    private final int OriginSize_Width = 300;
    /**
     * 窗口原始高度
     */
    private final int OriginSize_Height = 570;

    private static MenuItem filesViewer;

    /**
     * icon path
     */
    public static final String ICON_PATH = "/com/baiyimi/pan/ui/resource/icon.png";
    public static final String ICON_TRAY_PATH = "/com/baiyimi/pan/ui/resource/icon_tray.png";
    public static final String ICON_TRAY_W_PATH = "/com/baiyimi/pan/ui/resource/icon_tray_w.png";

    private ServerUIModule() throws Exception {
        setUIFont();
        (ServerUIModule.window = new JFrame("BaiyimiPan-服务器控制台")).setSize(OriginSize_Width, OriginSize_Height);
        ServerUIModule.window.setLocation(100, 100);
        ServerUIModule.window.setResizable(false);
        try {
            ServerUIModule.window.setIconImage(ImageIO.read(this.getClass().getResourceAsStream(ICON_PATH)));
        } catch (NullPointerException ex) {
        } catch (IOException ex2) {
        }
        if (SystemTray.isSupported()) {
            ServerUIModule.window.setDefaultCloseOperation(1);
            ServerUIModule.tray = SystemTray.getSystemTray();
            String iconType = ICON_TRAY_PATH;
            if (System.getProperty("os.name").toLowerCase().indexOf("window") >= 0) {
                iconType = ICON_TRAY_W_PATH;
            }
            (ServerUIModule.trayIcon = new TrayIcon(ImageIO.read(this.getClass().getResourceAsStream(iconType)))).setToolTip("网络文件系统-BaiyimiPan");
            trayIcon.setImageAutoSize(true);
            final PopupMenu pMenu = new PopupMenu();
            final MenuItem exit = new MenuItem("退出(Exit)");
            filesViewer = new MenuItem("文件...(Files)");
            final MenuItem show = new MenuItem("显示主窗口(Show)");
            trayIcon.addMouseListener(new MouseListener() {

                @Override
                public void mouseReleased(MouseEvent e) {
                    // TODO 自动生成的方法存根

                }

                @Override
                public void mousePressed(MouseEvent e) {
                    // TODO 自动生成的方法存根

                }

                @Override
                public void mouseExited(MouseEvent e) {
                    // TODO 自动生成的方法存根

                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    // TODO 自动生成的方法存根

                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    // TODO 自动生成的方法存根
                    if (e.getClickCount() == 2) {
                        show();
                    }
                }
            });
            exit.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO 自动生成的方法存根
                    exit();
                }
            });
            filesViewer.addActionListener((e) -> {
                filesViewer.setEnabled(false);
                fileIOUtil.setEnabled(false);
                Thread t = new Thread(() -> {
                    try {
                        ServerUIModule.fsv = FSViewer.getInstance();
                        fsv.show();
                    } catch (SQLException e1) {
                        // TODO 自动生成的 catch 块
                        JOptionPane.showMessageDialog(window, "错误：无法打开文件，文件系统可能已损坏，您可以尝试重启应用。", "错误",
                                JOptionPane.ERROR_MESSAGE);
                    }
                    filesViewer.setEnabled(true);
                    fileIOUtil.setEnabled(true);
                });
                t.start();
            });
            show.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    // TODO 自动生成的方法存根
                    show();
                }
            });
            pMenu.add(exit);
            pMenu.addSeparator();
            pMenu.add(filesViewer);
            pMenu.add(show);
            ServerUIModule.trayIcon.setPopupMenu(pMenu);
            ServerUIModule.tray.add(ServerUIModule.trayIcon);

        } else {
            ServerUIModule.window.setDefaultCloseOperation(1);
        }
        ServerUIModule.window.setLayout(new BoxLayout(ServerUIModule.window.getContentPane(), 3));
        final JPanel titlebox = new JPanel(new FlowLayout(1));
        titlebox.setBorder(new EmptyBorder(0, 0, (int) (-25 * proportion), 0));
        final JLabel title = new JLabel("baiyimi.pan");
        title.setFont(new Font("宋体", 1, (int) (30 * proportion)));
        titlebox.add(title);
        ServerUIModule.window.add(titlebox);
        final JPanel subtitlebox = new JPanel(new FlowLayout(1));
        subtitlebox.setBorder(new EmptyBorder(0, 0, (int) (-20 * proportion), 0));
        final JLabel subtitle = new JLabel("百亿米网络文件系统-服务器");
        subtitle.setFont(new Font("宋体", 0, (int) (13 * proportion)));
        subtitlebox.add(subtitle);
        ServerUIModule.window.add(subtitlebox);
        final JPanel statusBox = new JPanel(new GridLayout(4, 1));
        statusBox.setBorder(BorderFactory.createEtchedBorder());
        final JPanel serverStatus = new JPanel(new FlowLayout());
        serverStatus.setBorder(new EmptyBorder(0, 0, (int) (-8 * proportion), 0));
        serverStatus.add(new JLabel("服务器状态(Status)："));
        serverStatus.add(ServerUIModule.serverStatusLab = new JLabel("--"));
        statusBox.add(serverStatus);
        final JPanel portStatus = new JPanel(new FlowLayout());
        portStatus.setBorder(new EmptyBorder(0, 0, (int) (-8 * proportion), 0));
        portStatus.add(new JLabel("端口号(Port)："));
        portStatus.add(ServerUIModule.portStatusLab = new JLabel("--"));
        statusBox.add(portStatus);
        final JPanel addrStatus = new JPanel(new FlowLayout());
        addrStatus.setBorder(new EmptyBorder(0, 0, (int) (-8 * proportion), 0));
        addrStatus.add(new JLabel("日志等级(LogLevel)："));
        addrStatus.add(ServerUIModule.logLevelLab = new JLabel("--"));
        statusBox.add(addrStatus);
        final JPanel bufferStatus = new JPanel(new FlowLayout());
        bufferStatus.setBorder(new EmptyBorder(0, 0, (int) (-8 * proportion), 0));
        bufferStatus.add(new JLabel("下载缓冲区(Buffer)："));
        bufferStatus.add(ServerUIModule.bufferSizeLab = new JLabel("--"));
        statusBox.add(bufferStatus);
        ServerUIModule.window.add(statusBox);
        final JPanel buttonBox = new JPanel(new GridLayout(6, 1));
        buttonBox.add(ServerUIModule.start = new JButton("开启(Start)>>"));
        buttonBox.add(ServerUIModule.stop = new JButton("关闭(Stop)||"));
        buttonBox.add(ServerUIModule.resatrt = new JButton("重启(Restart)~>"));
        buttonBox.add(ServerUIModule.fileIOUtil = new JButton("文件(Files)[*]"));
        buttonBox.add(ServerUIModule.setting = new JButton("设置(Setting)[/]"));
        buttonBox.add(ServerUIModule.exit = new JButton("退出(Exit)[X]"));
        ServerUIModule.window.add(buttonBox);
        final JPanel outputBox = new JPanel(new FlowLayout(1));
        outputBox.add(new JLabel("[输出信息(Server Message)]："));
        (ServerUIModule.output = new JTextArea()).setLineWrap(true);
        output.setRows(3 + (int) (proportion));
        output.setSize((int) (292 * proportion), 100);
        ServerUIModule.output.setEditable(false);
        ServerUIModule.output.setForeground(Color.RED);
        ServerUIModule.output.getDocument().addDocumentListener(new DocumentListener() {

            @Override
            public void removeUpdate(DocumentEvent e) {
                // TODO 自动生成的方法存根

            }

            @Override
            public void insertUpdate(DocumentEvent e) {
                // TODO 自动生成的方法存根
                Thread t = new Thread(() -> {
                    if (output.getLineCount() >= 1000) {
                        int end = 0;
                        try {
                            end = output.getLineEndOffset(100);
                        } catch (Exception exc) {
                        }
                        output.replaceRange("", 0, end);
                    }
                    output.setCaretPosition(output.getText().length());
                });
                t.start();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                // TODO 自动生成的方法存根
                output.selectAll();
                output.setCaretPosition(output.getSelectedText().length());
                output.requestFocus();
            }
        });
        outputBox.add(new JScrollPane(ServerUIModule.output));
        ServerUIModule.window.add(outputBox);
        final JPanel bottombox = new JPanel(new FlowLayout(1));
        bottombox.setBorder(new EmptyBorder(0, 0, (int) (-30 * proportion), 0));
        bottombox.add(new JLabel("--百亿米@baiyimi--"));
        ServerUIModule.window.add(bottombox);
        ServerUIModule.start.setEnabled(false);
        ServerUIModule.stop.setEnabled(false);
        ServerUIModule.resatrt.setEnabled(false);
        ServerUIModule.setting.setEnabled(false);
        ServerUIModule.start.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                start.setEnabled(false);
                setting.setEnabled(false);
                fileIOUtil.setEnabled(false);
                if (filesViewer != null) {
                    filesViewer.setEnabled(false);
                }
                printMessage("启动服务器...");
                if (ss != null) {
                    serverStatusLab.setText(S_STARTING);
                    Thread t = new Thread(() -> {
                        if (ss.start()) {
                            printMessage("启动完成。正在检查服务器状态...");
                            if (st.getServerStatus()) {
                                printMessage("BaiyimiPan服务器已经启动，可以正常访问了。");
                            } else {
                                printMessage("BaiyimiPan服务器未能成功启动，请检查设置或查看异常信息。");
                            }
                        } else {
                            if (ConfigureReader.instance().getPropertiesStatus() != 0) {
                                switch (ConfigureReader.instance().getPropertiesStatus()) {
                                    case ConfigureReader.INVALID_PORT:
                                        printMessage("BaiyimiPan无法启动：端口设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_BUFFER_SIZE:
                                        printMessage("BaiyimiPan无法启动：缓存设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_FILE_SYSTEM_PATH:
                                        printMessage("BaiyimiPan无法启动：文件系统路径或某一扩展存储区设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_LOG:
                                        printMessage("BaiyimiPan无法启动：日志设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_VC:
                                        printMessage("BaiyimiPan无法启动：登录验证码设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_MUST_LOGIN_SETTING:
                                        printMessage("BaiyimiPan无法启动：必须登入设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_CHANGE_PASSWORD_SETTING:
                                        printMessage("BaiyimiPan无法启动：用户修改账户密码设置无效。");
                                        break;
                                    case ConfigureReader.INVALID_FILE_CHAIN_SETTING:
                                        printMessage("BaiyimiPan无法启动：永久资源链接设置无效。");
                                        break;
                                    default:
                                        printMessage("BaiyimiPan无法启动，请检查设置或查看异常信息。");
                                        break;
                                }
                            } else {
                                printMessage("BaiyimiPan无法启动，请检查设置或查看异常信息。");
                            }
                            serverStatusLab.setText(S_STOP);
                        }
                        updateServerStatus();
                    });
                    t.start();
                }
            }
        });
        ServerUIModule.stop.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                stop.setEnabled(false);
                resatrt.setEnabled(false);
                fileIOUtil.setEnabled(false);
                if (filesViewer != null) {
                    filesViewer.setEnabled(false);
                }
                printMessage("关闭服务器...");
                Thread t = new Thread(() -> {
                    if (cs != null) {
                        serverStatusLab.setText(S_STOPPING);
                        if (cs.close()) {
                            printMessage("关闭完成。正在检查服务器状态...");
                            if (st.getServerStatus()) {
                                printMessage("BaiyimiPan服务器未能成功关闭，如有需要，可以强制关闭程序（不安全）。");
                            } else {
                                printMessage("BaiyimiPan服务器已经关闭，停止所有访问。");
                            }
                        } else {
                            printMessage("BaiyimiPan服务器无法关闭，请手动结束本程序。");
                        }
                        updateServerStatus();
                    }
                });
                t.start();
            }
        });
        ServerUIModule.exit.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                fileIOUtil.setEnabled(false);
                if (filesViewer != null) {
                    filesViewer.setEnabled(false);
                }
                exit();
            }
        });
        ServerUIModule.resatrt.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                stop.setEnabled(false);
                resatrt.setEnabled(false);
                fileIOUtil.setEnabled(false);
                if (filesViewer != null) {
                    filesViewer.setEnabled(false);
                }
                Thread t = new Thread(() -> {
                    printMessage("正在重启服务器...");
                    if (cs.close()) {
                        if (ss.start()) {
                            printMessage("重启成功，可以正常访问了。");
                        } else {
                            printMessage("错误：服务器已关闭但未能重新启动，请尝试手动启动服务器。");
                        }
                    } else {
                        printMessage("错误：无法关闭服务器，请尝试手动关闭。");
                    }
                    updateServerStatus();
                });
                t.start();
            }
        });
        ServerUIModule.setting.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // TODO 自动生成的方法存根
                ServerUIModule.sw = SettingWindow.getInstance();
                Thread t = new Thread(() -> {
                    sw.show();
                });
                t.start();
            }
        });
        ServerUIModule.fileIOUtil.addActionListener((e) -> {
            ServerUIModule.fileIOUtil.setEnabled(false);
            if (ServerUIModule.filesViewer != null) {
                ServerUIModule.filesViewer.setEnabled(false);
            }
            Thread t = new Thread(() -> {
                try {
                    ServerUIModule.fsv = FSViewer.getInstance();
                    fsv.show();
                } catch (SQLException e1) {
                    // TODO 自动生成的 catch 块
                    Printer.instance.print("错误：无法读取文件，文件系统可能已经损坏，您可以尝试重启应用。");
                }
                ServerUIModule.fileIOUtil.setEnabled(true);
                if (ServerUIModule.filesViewer != null) {
                    ServerUIModule.filesViewer.setEnabled(true);
                }
            });
            t.start();
        });
        modifyComponentSize(ServerUIModule.window);
    }

    public void show() {
        ServerUIModule.window.setVisible(true);
        updateServerStatus();
    }

    public static void setOnCloseServer(final OnCloseServer cs) {
        ServerUIModule.cs = cs;
    }

    public static ServerUIModule getInsatnce() throws Exception {
        if (ServerUIModule.instance == null) {
            ServerUIModule.instance = new ServerUIModule();
        }
        return ServerUIModule.instance;
    }

    public static void setStartServer(final OnStartServer ss) {
        ServerUIModule.ss = ss;
    }

    public static void setGetServerStatus(final GetServerStatus st) {
        ServerUIModule.st = st;
        SettingWindow.st = st;
    }

    public void updateServerStatus() {
        if (ServerUIModule.st != null) {
            Thread t = new Thread(() -> {
                if (ServerUIModule.st.getServerStatus()) {
                    ServerUIModule.serverStatusLab.setText(S_START);
                    ServerUIModule.start.setEnabled(false);
                    ServerUIModule.stop.setEnabled(true);
                    ServerUIModule.resatrt.setEnabled(true);
                    ServerUIModule.setting.setEnabled(false);
                } else {
                    ServerUIModule.serverStatusLab.setText(S_STOP);
                    ServerUIModule.start.setEnabled(true);
                    ServerUIModule.stop.setEnabled(false);
                    ServerUIModule.resatrt.setEnabled(false);
                    ServerUIModule.setting.setEnabled(true);
                }
                fileIOUtil.setEnabled(true);
                if (filesViewer != null) {
                    filesViewer.setEnabled(true);
                }
                ServerUIModule.portStatusLab.setText(ServerUIModule.st.getPort() + "");
                if (ServerUIModule.st.getLogLevel() != null) {
                    switch (ServerUIModule.st.getLogLevel()) {
                        case Event: {
                            ServerUIModule.logLevelLab.setText(L_ALL);
                            break;
                        }
                        case None: {
                            ServerUIModule.logLevelLab.setText(L_NONE);
                            break;
                        }
                        case Runtime_Exception: {
                            ServerUIModule.logLevelLab.setText(L_EXCEPTION);
                            break;
                        }
                        default: {
                            ServerUIModule.logLevelLab.setText("无法获取(?)");
                            break;
                        }
                    }
                }
                ServerUIModule.bufferSizeLab.setText(ServerUIModule.st.getBufferSize() / 1024 + " KB");
            });
            t.start();
        }
    }

    private void exit() {
        ServerUIModule.start.setEnabled(false);
        ServerUIModule.stop.setEnabled(false);
        ServerUIModule.exit.setEnabled(false);
        ServerUIModule.resatrt.setEnabled(false);
        ServerUIModule.setting.setEnabled(false);
        this.printMessage("退出程序...");
        if (ServerUIModule.cs != null) {
            final Thread t = new Thread(() -> {
                if (ServerUIModule.st.getServerStatus()) {
                    ServerUIModule.cs.close();
                }
                System.exit(0);
                return;
            });
            t.start();
        } else {
            System.exit(0);
        }
    }

    public void printMessage(final String context) {
        ServerUIModule.output.append("[" + this.getFormateDate() + "]" + context + "\n");
    }

    private String getFormateDate() {
        if (null == sdf) {
            sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        }
        if (ServerUIModule.ti != null) {
            final Date d = ServerUIModule.ti.get();
            return sdf.format(d);
        }
        return sdf.format(new Date());
    }

    public static void setGetServerTime(final GetServerTime ti) {
        ServerUIModule.ti = ti;
    }

    public static void setUpdateSetting(final UpdateSetting us) {
        SettingWindow.us = us;
    }
}